package @modelPackage@;

import org.hibernate.Session;
import org.hibernate.LockMode;
import org.hibernate.Criteria;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.*;

import java.io.Serializable;
import java.util.List;

/**
 * Help class for manipulation with hibernate session
 *
 * @author Michal Rost
 */
public class SessionUtils {

  /**
   * Finds entity with specifed ID
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param id identification of entity
   * @param lock lockmode
   * @return entity instance
   */
  @SuppressWarnings("unchecked")
  public static Object findById(Session session, Class<?> persistentClass, Serializable id, boolean lock) {
    if (lock) {
      return session.load(persistentClass, id, LockMode.UPGRADE);
    } else {
      return session.load(persistentClass, id);
    }
  }

  /**
   * Finds all entity instances
   * @param session hibernate session
   * @param  persistentClass persistent class
   * @return list of entity instances
   */
  @SuppressWarnings("unchecked")
  public static List findAll(Session session, Class<?> persistentClass) {
    return findByCriteria(session, persistentClass);
  }


  /**
   * Finds entity instances by given criteria
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param criterions hibernate criterions
   * @return list of entity instances
   */
  @SuppressWarnings("unchecked")
  static public List findByCriteria(Session session, Class<?> persistentClass, Criterion... criterions) {
    return createCriteria(session, persistentClass, criterions).list();
  }

  /**
   * Finds entity instances by given criteria
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param firstResult index of first row in result
   * @param maxResults max number of rows
   * @param criterions hibernate criterions
   * @return list of entity instances
   */
  @SuppressWarnings("unchecked")
  public static List findByCriteria(Session session, Class<?> persistentClass, int firstResult, int maxResults,
                                Criterion... criterions) {
    Criteria crit = createCriteria(session, persistentClass, criterions);
    crit.setFirstResult(firstResult);
    crit.setMaxResults(maxResults);
    return crit.list();
  }

  /**
   * Finds entity instances by given criteria
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param firstResult index of first row in result
   * @param maxResults max number of rows
   * @param orderBy name of "order by" column
   * @param asc order direction (true for ascending, false for descending)
   * @param criterions hibernate criterions
   * @return list of entity instances
   */
  @SuppressWarnings("unchecked")
  public static List findByCriteria(Session session, Class<?> persistentClass, int firstResult, int maxResults,
                                    String orderBy, boolean asc, Criterion... criterions) {
    Criteria crit = createCriteria(session, persistentClass, criterions);
    crit.setFirstResult(firstResult);
    crit.setMaxResults(maxResults);
    if (orderBy != null && !"".equals(orderBy)) {
      if (asc) {
        crit.addOrder(Property.forName(orderBy).asc());
      } else {
        crit.addOrder(Property.forName(orderBy).desc());
      }
    }
    return crit.list();
  }

  /**
   * Finds number of rows that meeting given criteria
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param criterions hibernate criterions
   * @return number of rows
   */
  public static int findCountByCriteria(Session session, Class<?> persistentClass, Criterion... criterions) {
    Criteria crit = createCriteria(session, persistentClass, criterions);
    crit.setProjection(Projections.rowCount());
    return (Integer) crit.list().get(0);
  }

  /**
	 * Finds entity instances by given criterium
   * @param session hibernate session
   * @param persistentClass persistent class
	 * @param propertyName value
	 * @param ignoreCase if true case will be ignored
	 * @return list of entity instances
	 */
	public static List findByPropertyName(Session session, Class<?> persistentClass, String propertyName,
                                        boolean ignoreCase) {
		Criteria crit = session.createCriteria(persistentClass);
		if (ignoreCase) {
			crit.add(Restrictions.eq("propertyName", propertyName).ignoreCase());
		} else {
			crit.add(Restrictions.eq("propertyName", propertyName));
		}
		return crit.list();
	}

  /**
   * Create criteria querry from given criterions
   * @param session hibernate session
   * @param persistentClass persistent class
   * @param criterions hibernate criterions
   * @return criteria
   */
  protected static Criteria createCriteria(Session session, Class<?> persistentClass, Criterion... criterions) {
    Criteria crit = session.createCriteria(persistentClass);
    for (Criterion c : criterions) {
      crit.add(c);
    }
    return crit;
  }
}
